/*
 *  MainComponent.cpp
 *  haydxn_tutorial
 *
 *  Created by David Rowland on 27/12/2008.
 *  Copyright 2008 UWE. All rights reserved.
 *
 */

#include "MainComponent.h"

//==============================================================================
MainComponent::MainComponent ()	:	currentArtist(0),
									currentTrack(0),
									tracksPlayed(0),
									buttonJustPressed(false)
{
//	setLookAndFeel(new OldSchoolLookAndFeel);
	
	// set up buttons
	addAndMakeVisible(startButton = new TextButton(T("Start"), T("Start the player")));
	startButton->setConnectedEdges(Button::ConnectedOnRight);
	startButton->setColour(TextButton::buttonColourId, Colours::green);
	startButton->addButtonListener(this);
	
	addAndMakeVisible(pauseButton = new TextButton(T("Pause"), T("Pause the audio")));
	pauseButton->setConnectedEdges(Button::ConnectedOnRight + Button::ConnectedOnLeft);
	pauseButton->setColour(TextButton::buttonColourId, Colours::orange);
	pauseButton->setClickingTogglesState(true);
	pauseButton->addButtonListener(this);

	addAndMakeVisible(stopButton = new TextButton(T("Stop"), T("Stop the player")));
	stopButton->setConnectedEdges(Button::ConnectedOnLeft);
	stopButton->setColour(TextButton::buttonColourId, Colours::red);
	stopButton->addButtonListener(this);
	
	addAndMakeVisible(audioSettingButton = new TextButton(T("Audio Settings"), T("Display the audio settings")));
	audioSettingButton->addButtonListener(this);
	
	addAndMakeVisible(tracksPlayedLabel = new Label(T("tracksPlayedLabel"), String(tracksPlayed)));
	(new Label(T("tracksPlayedLabel"), T("Tracks played:")))->attachToComponent(tracksPlayedLabel, true);
	
	addAndMakeVisible(tracksToPlaySlider = new Slider(T("tracksToPlaySlider")));
	tracksToPlaySlider->setSliderStyle(Slider::IncDecButtons);
	tracksToPlaySlider->setIncDecButtonsMode(Slider::incDecButtonsDraggable_AutoDirection);
	tracksToPlaySlider->setRange(0, 10, 1);
	tracksToPlaySlider->setValue(4);
	(new Label(T("tracksToPlayLabel"), T("Req. tracks:")))->attachToComponent(tracksToPlaySlider, true);
	
	addAndMakeVisible(distanceSlider = new Slider("distanceSlider"));
	
	
	// Initialise the audio device
	const String error (audioDeviceManager.initialise (1, /* number of input channels */
													   2, /* number of output channels */
													   0, /* no XML settings.. */
													   true  /* select default device on failure */));
	if (error.isNotEmpty())
	{
		AlertWindow::showMessageBox (AlertWindow::WarningIcon,
									 T("Fender Installation"),
									 T("Couldn't open an output device!\n\n") + error);
	}
	else
	{
		// Connect the mixer to our source player.
		audioSourcePlayer.setSource (&mixerSource);
		
		// Start the IO device pulling its data from our callback..
		audioDeviceManager.setAudioCallback (this);
		
		// Find the Sounds directory
		File appDirectory = File::getSpecialLocation(File::currentApplicationFile).getParentDirectory();
		File soundsDirectory = appDirectory.getChildFile(T("../../../sounds"));
		
		// Check to see if the sounds directory is there
		if (!soundsDirectory.isDirectory())
			DBG_PRINTF(( T("\nNo Sounds Directory Found\n") ));
		DBG_PRINTF(( String("App Directory: ") << appDirectory.getFullPathName() ));
		DBG_PRINTF(( String("Sounds Directory: ") << soundsDirectory.getFullPathName() ));
		
		// find all the .aif files in our sounds directory and store them in the audioFiles
		soundsDirectory.findChildFiles(audioFiles, File::findFiles, false, T("*.aif"));
		soundsDirectory.findChildFiles(audioFiles, File::findFiles, false, T("*.wav"));
		
		// iterate through our files, making a player for each
		for (int i = 0; i < audioFiles.size(); i++ )
		{
			String soundFilePath = audioFiles[i]->getFullPathName();
			DBG_PRINTF(( soundFilePath ));
			String fileName = audioFiles[i]->getFileName();
			DBG_PRINTF(( fileName ));
/*			// a new instance of one of our player objects
			// initialised with the path of this sound file
			filePlayers.add (new AudioFilePlayer(soundFilePath));
			filePlayers[i]->setButtonText(filePlayers[i]->fileName.substring(0, 3));
			filePlayers[i]->setConnectedEdges(TextButton::ConnectedOnLeft + TextButton::ConnectedOnRight);
			filePlayers[i]->setClickingTogglesState(true);
			filePlayers[i]->setRadioGroupId(1);
			filePlayers[i]->addButtonListener(this);
			addAndMakeVisible(filePlayers[i]);
*/			
			int artistNum  = (fileName.substring(0, 1).getIntValue());
			int trackNum = (fileName.substring(2, 3).getIntValue());
			String name = fileName.substring(0, 3);

			printf("First then second: %i %i\n",artistNum, trackNum );
			// create a button for it
			if ( trackNum == 0 )
				filePlayers.add( new OwnedArray<AudioFilePlayer> );
			
//			if ( filePlayers[artistNum] != 0 )
//			{
				filePlayers[artistNum]->add(new AudioFilePlayer(soundFilePath, name) );
				AudioFilePlayer* currentFilePlayer = (*filePlayers[artistNum])[trackNum];
				currentFilePlayer->setConnectedEdges(TextButton::ConnectedOnLeft + TextButton::ConnectedOnRight);
				currentFilePlayer->setClickingTogglesState(true);
				currentFilePlayer->setRadioGroupId(1);
				currentFilePlayer->addChangeListener (this);
				currentFilePlayer->addButtonListener(this);
				addAndMakeVisible(currentFilePlayer);			
//			}
			/*AudioFilePlayer**/ currentFilePlayer = (*filePlayers[artistNum])[trackNum];
			// plug it in to our mixer
			mixerSource.addInputSource (currentFilePlayer, false);
		}
	}
}

MainComponent::~MainComponent ()
{
	// zero the device manager and source player to avoid crashing
	audioDeviceManager.setAudioCallback (0);
	audioSourcePlayer.setSource (0);
	
	// delete the owned array's contents
	filePlayers.clear();
	
	deleteAllChildren();
}

//==============================================================================
void MainComponent::resized ()
{
	startButton->setBounds(10, 10, (getWidth()-20)/3, 20);
	pauseButton->setBounds(10+((getWidth()-20)/3), 10, (getWidth()-20)/3, 20);
	stopButton->setBounds(10+2*((getWidth()-20)/3), 10, (getWidth()-20)/3, 20);
    audioSettingButton->setBounds(10, 40, getWidth()-20, 20);
					  
	distanceSlider->setBounds(10, 70, getWidth()-20, 20);
	
	tracksPlayedLabel->setBounds(getWidth()*0.5f - 20, 100, 20, 20);
	tracksToPlaySlider->setBounds(getWidth()*0.5f + 80, 100, 50, 20);
	
	int buttonSize = 20;
	for (int i = 0; i < filePlayers.size(); i++)
	{
		for (int c = 0; c < (*filePlayers[i]).size(); c++)
		{
			AudioFilePlayer* currentFilePlayer = (*(filePlayers[i]))[c];
			
			int artistNum = currentFilePlayer->fileName.substring(0,1).getIntValue();
			int trackNum = currentFilePlayer->fileName.substring(2,3).getIntValue();
			DBG_PRINTF((String("Artist/Track Number: ") << artistNum << String("_") << trackNum ));
			
			int x = 10 + (20 * trackNum) + (10 * trackNum);
			int y = 130+ (20 * artistNum) + (10 * artistNum);
			DBG_PRINTF((String("X-coord: ") << x << String(" Y-coord: ") << y ));
			
			(*(filePlayers[i]))[c]->setBounds(x, y, buttonSize, buttonSize );
		}
	}
	
//	(*(filePlayers[0]))[0]->setBounds(10, 100, buttonSize, buttonSize );
//	(*(filePlayers[0]))[1]->setBounds(10, 130, buttonSize, buttonSize );
	
	
//	for (int i = 0; i < filePlayers.size(); i++)
//	{
//		int artistNum = filePlayers[i]->fileName.substring(0,1).getIntValue();
//		int trackNum = filePlayers[i]->fileName.substring(2,3).getIntValue();
//		
//		filePlayers[i]->setBounds(10 + (20 * trackNum) + (10 * trackNum),
//								  100+ (20 * artistNum) + (10 * artistNum),
//								  buttonSize, buttonSize );
//	}
}

void MainComponent::paint (Graphics& g)
{
}

void MainComponent::repaint()
{
}		
//==============================================================================

void MainComponent::buttonClicked(Button* clickedButton)
{
	if (clickedButton == audioSettingButton)
	{
		// Create an AudioDeviceSelectorComponent which contains the audio choice widgets...
		AudioDeviceSelectorComponent audioSettingsComp (audioDeviceManager,
														0, 1,
														2, 2,
														true,
														false,
														true,
														false);
		
		// ...and show it in a DialogWindow...
		audioSettingsComp.setSize (500, 400);
		
		DialogWindow::showModalDialog (T("Audio Settings"),
									   &audioSettingsComp,
									   this,
									   Colours::azure,
									   true);
	}
	
	else if (clickedButton == startButton)
		(*(filePlayers[0]))[0]->triggerClick();
	
	else if (clickedButton == stopButton)
	{
		(*(filePlayers[currentArtist]))[currentTrack]->stop();
		buttonJustPressed = true;
	}
		
	else if (clickedButton == pauseButton)
		(*(filePlayers[currentArtist]))[currentTrack]->pause();
	
	else
	{
		for (int i = 0; i < filePlayers.size(); i++)
		{
			for (int c = 0; c < (*filePlayers[i]).size(); c++)
			{
				AudioFilePlayer* currentFilePlayer = (*(filePlayers[i]))[c];
				if ( clickedButton == currentFilePlayer )
				{
					(*(filePlayers[currentArtist]))[currentTrack]->stop();
					currentFilePlayer->setPosition(0.0);
					
					// only play the sound if we're not paused
					if (!pauseButton->getToggleState())
						currentFilePlayer->startFromZero();
					
					currentArtist = i;
					currentTrack = c;
					tracksPlayed++;
					if (clickedButton == (*(filePlayers[currentArtist]))[0])
						tracksPlayed = 0;
					buttonJustPressed = true;
					DBG_PRINTF(( String("Button ") << i<<c <<String(" pressed") ));
				}
			}
		}
	}
	
	// set the text
	tracksPlayedLabel->setText(String((double)tracksPlayed), false);

//	else
//		for (int i = 0; i < filePlayers.size(); i++)
//		{
//			if (clickedButton == filePlayers[i])
//			{
//				filePlayers[currentTrack]->stop();
//				filePlayers[i]->startFromZero();
//				currentTrack = i;
//			}
//		}
}

void MainComponent::changeListenerCallback(void* pointer)
{
	if ( !pauseButton->getToggleState() && !buttonJustPressed) // if the audio is not paused
	{
		for (int i = 0; i < filePlayers.size(); i++)
		{
			for (int c = 0; c < (*filePlayers[i]).size(); c++)
			{
				//=========================================================
				// here i is the artist that has stopped or started and
				// c is the track for that artist
				//=========================================================
				AudioFilePlayer* currentFilePlayer = (*(filePlayers[i]))[c];
				if ( pointer == currentFilePlayer )
				{
					int noArtists = filePlayers.size();
					int noCurrentTracks = (*filePlayers[i]).size();

					if (currentFilePlayer->isPlaying())	// if the file is playing
					{
						DBG_PRINTF(( String("File playing: ") << currentFilePlayer->fileName ));
					}
					else if (!currentFilePlayer->isPlaying())	// if the file stopped
					{
						DBG_PRINTF(( String("File stopped: ") << currentFilePlayer->fileName ));
						// try to play the next track for this artist
//						if ( c < noCurrentTracks-1 )
//						{
//							DBG_PRINTF(( String("Next track to be played: ") <<currentArtist << c+1 ));
//							(*(filePlayers[i]))[c + 1]->triggerClick();
//						}
						if ( tracksPlayed < (int)tracksToPlaySlider->getValue() )
						{
							int nextTrack = Random::getSystemRandom().nextInt((filePlayers[i]->size())-2) + 1;
							// make sure we dont play the same track twice if there are more than three
							if (filePlayers[i]->size() > 3)
							{
								while (nextTrack == currentTrack)
								{
									nextTrack = Random::getSystemRandom().nextInt((filePlayers[i]->size())-2);
									nextTrack++;
								}
							}
							(*(filePlayers[i]))[nextTrack]->triggerClick();
						}
						// if enough have been played, play the last track
						else if (tracksPlayed >= (int)tracksToPlaySlider->getValue())
						{
							(*(filePlayers[i]))[filePlayers[i]->size()-1]->triggerClick();
						}
						
						// if the last track has just played then play the next artists first track
						if ( c >= noCurrentTracks-1)
						{
							if ( i < noArtists-1)
							{
								DBG_PRINTF(( String("Next track to be played: ") <<i+1 << 0 ));
								(*(filePlayers[i + 1]))[0]->triggerClick();
							}
							else
							{
								DBG_PRINTF(( String("Next track to be played: ") <<0 << 0 ));
								tracksPlayed = 0;
								(*(filePlayers[0]))[0]->triggerClick();
							}
							tracksPlayed = 0;
						}
					}
				}
			}
		}
	}
	buttonJustPressed = false;
}

//==============================================================================
// Audio device callbacks
//==============================================================================
/**
 Audio Device Callback method to process audio.
 
 */
void MainComponent::audioDeviceIOCallback (const float** inputChannelData,
							int totalNumInputChannels,
							float** outputChannelData,
							int totalNumOutputChannels,
							int numSamples)
{		
	// pass the audio callback on to our player source
	audioSourcePlayer.audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples);
	
	
	// Adjust the volume level of the audio
	//			audioSourcePlayer.setGain(volumeLevel);
	
}

void MainComponent::audioDeviceAboutToStart (AudioIODevice* device)
{
	DBG("Audio device about to start");
	audioSourcePlayer.audioDeviceAboutToStart (device);
}

void MainComponent::audioDeviceStopped()
{
	DBG("Audio device stopped");
	audioSourcePlayer.audioDeviceStopped();
}
